---
title: "Notifications"
description: "Send notifications to clients and receive notifications from clients"
icon: "bell"
---

MCP supports bidirectional notifications between servers and clients. Notifications are one-way JSON-RPC messages that don't expect a response.

**Server → Client**: Send notifications to signal events, status changes, or broadcast messages.

**Client → Server**: Receive notifications when clients update their roots or other state.

<Note>
For information on handling notifications in your client application, see [Client Notifications](/typescript/client/notifications).
</Note>

<Tip>
Check out the [complete notifications example](https://github.com/mcp-use/mcp-use/tree/main/libraries/typescript/packages/mcp-use/examples/server/notifications) for a working implementation with progress tracking, custom broadcasts, and resource updates.
</Tip>


<Warning>
Notifications only work in **stateful mode** where clients maintain persistent sessions. In stateless edge environments, notifications are not supported.
</Warning>

## Sending Notifications

### Broadcasting to All Clients

Send a notification to all connected clients:

```typescript
import { MCPServer } from "mcp-use/server";

const server = new MCPServer({
  name: "my-server",
  version: "1.0.0"
});

// Later, send to all connected clients
await server.sendNotification("custom/status-update", {
  status: "ready",
  timestamp: Date.now()
});

// you can also send to a speocific client by session ID
await server.sendNotificationToSession(sessionId, "custom/status-update", {
  status: "ready",
  timestamp: Date.now()
});

```

### Sending to the current client

Send a notification to the current client:

```typescript
server.tool({
  name: 'send-notification',
  description: 'Send a notification to the current client',
}, async (params, ctx) => {
  await ctx.sendNotification("custom/welcome", { message: "Hello, client!" });
});
```


### Sending to a Specific Client

Send a notification to a specific session:

```typescript
// Get all active session IDs
const sessions = server.getActiveSessions();
console.log(`${sessions.length} clients connected`);

// Send to a specific session
if (sessions.length > 0) {
  const success = await server.sendNotificationToSession(
    sessions[0],
    "custom/welcome",
    { message: "Hello, client!" }
  );
  
  if (!success) {
    console.log("Session not found or expired");
  }
}
```

### Built-in Notification Types

MCP defines standard notification methods that clients may handle:

#### Tools List Changed

Notify clients when the available tools have changed:

```typescript
await server.sendNotification("notifications/tools/list_changed");
```

#### Resources List Changed

Notify clients when resources have been updated:

```typescript
await server.sendNotification("notifications/resources/list_changed");
```

#### Prompts List Changed

Notify clients when prompts have changed:

```typescript
await server.sendNotification("notifications/prompts/list_changed");
```

#### Progress Notifications

Progress notifications (`notifications/progress`) are used to keep clients informed during long-running operations and prevent timeouts. When a client calls a tool with a `progressToken`, the server can send progress updates.

**Automatic Progress in Sampling**

When using `ctx.sample()` in tool callbacks, progress notifications are automatically sent every 5 seconds:

```typescript
server.tool({
  name: 'long_llm_task',
  cb: async (params, ctx?: ToolContext) => {
    if (!ctx) return { content: [{ type: 'text', text: 'No context' }] }
    
    // Progress notifications are sent automatically every 5 seconds
    const result = await ctx.sample({
      messages: [{ role: 'user', content: { type: 'text', text: params.prompt } }]
    })
    
    return { content: [{ type: 'text', text: result.content.text }] }
  }
})
```

**Manual Progress Reporting**

You can also send progress notifications manually using `ctx.reportProgress()`:

```typescript
server.tool({
  name: 'process_data',
  cb: async (params, ctx?: ToolContext) => {
    if (ctx?.reportProgress) {
      await ctx.reportProgress(0, 100, 'Starting...')
      
      // Process data in stages
      await processStage1()
      await ctx.reportProgress(33, 100, 'Stage 1 complete')
      
      await processStage2()
      await ctx.reportProgress(66, 100, 'Stage 2 complete')
      
      await processStage3()
      await ctx.reportProgress(100, 100, 'Complete')
    }
    
    return { content: [{ type: 'text', text: 'Done' }] }
  }
})
```

**How Progress Prevents Timeouts**

According to the MCP specification, when a client has `resetTimeoutOnProgress: true` enabled:
- Each progress notification resets the client's timeout counter
- This allows operations to run indefinitely as long as progress is reported
- The default timeout is 60 seconds, but with progress notifications, operations can take much longer

**Progress Notification Format**

Progress notifications follow this structure:

```typescript
{
  method: "notifications/progress",
  params: {
    progressToken: number,  // Token from the original request
    progress: number,       // Current progress value
    total?: number,         // Total progress (if known)
    message?: string        // Optional status message
  }
}
```

### Custom Notifications

You can send custom notifications with any method name and parameters:

```typescript
// Use a namespace prefix for custom notifications
await server.sendNotification("custom/user-joined", {
  userId: "user-123",
  username: "alice",
  joinedAt: new Date().toISOString()
});

await server.sendNotification("custom/data-updated", {
  resourceId: "res-456",
  changes: ["field1", "field2"]
});
```


## Receiving Notifications

### Roots Changed

Clients can notify the server when their available roots (directories/files) change. Register a handler to respond to these changes:

```typescript
import { MCPServer } from "mcp-use/server";

const server = new MCPServer({
  name: "my-server",
  version: "1.0.0"
});

// Handle roots/list_changed from clients
server.onRootsChanged(async (roots) => {
  console.log(`Client updated roots: ${roots.length} root(s)`);
  
  roots.forEach(root => {
    console.log(`  - ${root.name || "unnamed"}: ${root.uri}`);
  });
  
  // You can use the new roots to adjust server behavior
  // For example, update which files the server can access
});
```

### Requesting Roots from a Client

You can also request the current roots from a specific client session:

```typescript
const sessions = server.getActiveSessions();

if (sessions.length > 0) {
  const roots = await server.listRoots(sessions[0]);
  
  if (roots) {
    console.log(`Client has ${roots.length} roots:`);
    roots.forEach(r => console.log(`  - ${r.uri}`));
  }
}
```

### Root Type

```typescript
interface Root {
  uri: string;      // Must start with "file://"
  name?: string;    // Optional human-readable name
}
```

## Next Steps

- [Client Notifications](/typescript/client/notifications) - Handle notifications in your client application
- [Tools Guide](./tools) - Create tools that send notifications
- [Configuration](./configuration) - Configure session management
- [Examples](./examples) - More notification examples

